package club.babyf.nativeai.config;

import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import okhttp3.OkHttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

/**
 * HttpConfig.
 *
 * @author zhanglei.
 * @date 2025/2/17 17:28.
 * @description Http配置.
 */
@Configuration
public class HttpConfig {

    /**
     * 实例化OkHttpClient
     *
     * @return OkHttpClient
     */
    @Bean
    public OkHttpClient okHttpClient() {
        return new OkHttpClient();
    }

    /**
     * 实例化WebClient
     *
     * @return WebClient
     */
    @Bean
    public WebClient webClient() {
        // maxConnections：设置连接池中的最大连接数。
        // pendingAcquireMaxCount：当连接池已满时，最大的等待队列长度，超过这个长度会抛出异常。
        // pendingAcquireTimeout：获取连接的最大等待时间。
        // maxIdleTime：连接的最大空闲时间，超过这个时间，连接会被关闭。
        // maxLifeTime：连接的最大生命周期时间，超过这个时间，连接会被关闭。

        // Create a ConnectionProvider with pool configurations
        ConnectionProvider connectionProvider = ConnectionProvider.builder("custom")
                // Maximum number of connections in the pool
                .maxConnections(50)
                // Maximum number of pending acquire
                .pendingAcquireMaxCount(100)
                // Timeout for acquiring a connection
                .pendingAcquireTimeout(Duration.ofSeconds(60))
                // Maximum idle time for connections
                .maxIdleTime(Duration.ofSeconds(20))
                // Maximum life time for connections
                .maxLifeTime(Duration.ofMinutes(5))
                .build();

        // Create a customized HttpClient with connection pooling
        HttpClient httpClient = HttpClient.create(connectionProvider)
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 60000)
                .doOnConnected(conn ->
                        conn.addHandlerLast(new ReadTimeoutHandler(1, TimeUnit.MINUTES))
                                .addHandlerLast(new WriteTimeoutHandler(1, TimeUnit.MINUTES)));

        // Create a WebClient that uses the customized HttpClient
        return WebClient.builder()
                .exchangeStrategies(ExchangeStrategies.builder()
                        .codecs(configurer -> configurer.defaultCodecs()
                                // 16MB buffer size
                                .maxInMemorySize(16 * 1024 * 1024))
                        .build())
                .clientConnector(new ReactorClientHttpConnector(httpClient))
                .build();
    }

}
